package com.small.sentinel.slots.nodeselectors;

import com.small.common.core.spi.Spi;
import com.small.common.designPattern.behavioral.chainOfResponsibility.slotchain.AbstractLinkedProcessorSlot;
import com.small.sentinel.Constants;
import com.small.sentinel.Context;
import com.small.sentinel.node.DefaultNode;
import com.small.sentinel.slots.SentinelResource;

import java.util.HashMap;
import java.util.Map;

@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<SentinelResource> {

    private volatile Map<String, DefaultNode> map = new HashMap(10);

    @Override
    public void entry(SentinelResource resource) throws Throwable {

        Context context = resource.getContext();
        DefaultNode node = map.get(context.getName());
        if (node == null) {
            synchronized (this) {
                if (node == null) {
                    node = new DefaultNode(resource.getResourceWrapper(), null);
                    HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
                    cacheMap.putAll(map);
                    cacheMap.put(context.getName(), node);
                    map = cacheMap;
                    ((DefaultNode) context.getLastNode()).addChild(node);
                }
            }
        }
        context.setCurNode(node);
        resource.setDefaultNode(node);
        fireEntry(resource);
    }

    @Override
    public void exit(SentinelResource resource) throws Throwable {
        fireExit(resource);
    }
}
